package com.example.mybatislearn.common.mapper.converter;

import com.example.mybatislearn.common.lang.Enumerable;
import com.example.mybatislearn.common.lang.Pair;
import com.example.mybatislearn.common.mapper.converter.customer.SmartTypeConverter;
import com.example.mybatislearn.common.mapper.util.ResolveTypeUtils;
import org.dozer.CustomConverter;

import java.util.HashMap;
import java.util.Map;

public class SmartCustomConverter implements CustomConverter{

    private static Map<Pair<Class,Class>, SmartTypeConverter> smartTypeConverterHashMap = new HashMap<>();

    private static Class<?>[] superClassArray = new Class<?>[]{Enumerable.class};


    @Override
    public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class<?> destinationClass, Class<?> sourceClass) {
        SmartTypeConverter smartTypeConverter = getTypeConverter(destinationClass,sourceClass);
        if(smartTypeConverter != null) {
            return smartTypeConverter.convert(existingDestinationFieldValue,sourceFieldValue,destinationClass,sourceClass);
        }
        return existingDestinationFieldValue;
    }

    public static void addSmartTypeConverter(SmartTypeConverter smartTypeConverter) {
        //解析出smartCustom 的源类和目标类
        smartTypeConverterHashMap.put(ResolveTypeUtils.resolveTypeConverterKey(smartTypeConverter.getClass()),smartTypeConverter);
    }


    private SmartTypeConverter getTypeConverter(Class<?> destinationClass, Class<?> sourceClass) {
        // 针对Enumerable类型特殊处理下
        Class<?> destClass = convertClass(destinationClass);
        Class<?> srcClass = convertClass(sourceClass);

        SmartTypeConverter typeConverter = smartTypeConverterHashMap.get(new Pair<>(srcClass, destClass));
        return typeConverter;
    }

    private Class<?> convertClass(Class<?> orgiClass) {
        Class<?> targetClass = orgiClass;
        for (Class<?> each : superClassArray) {
            if (each.isAssignableFrom(targetClass)) {
                targetClass = each;
                break;
            }
        }
        return targetClass;
    }

}
